# pymq - The python based Message Queue
#
# Copyright(C) 2010, Dhruv Matani(dhuvbird@gmail.com)
#
# pymq is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# pymq is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with pymq. If not, see
# <http://www.gnu.org/licenses/>.
#


from queue import begin
from optparse import OptionParser
import medusa.logger as medusa_logger
from queue import null_logger
import logging
import sys

PYMQ_VERSION="0.2"

# Note: If you are hacking at the code:
#
# Either call error_enqeue()/done_enqueue() OR forward the request to
# some other system OR store the request for future processing. PLEASE DO
# NOT DO BOTH OR EAT UP THE PACKET.

DataStore = None
logger    = None
cluster   = None
master    = None
inactive  = None
port      = None
name      = None
cStr      = None

def profile_run():
    try:
        begin.run(port=port, logger=logger, DataStore=DataStore,
                  inactive=inactive, cluster=cluster,
                  master=master, name=name, connectionString=cStr)
    except KeyboardInterrupt:
        pass

def main(argc, argv):
    logging.basicConfig(level=logging.DEBUG)
    usage = "usage: python %prog [options]"
    parser = OptionParser(usage=usage, version="%prog v" + PYMQ_VERSION)
    parser.add_option("-n", "--name", default="morpheus",
                      action="store", dest="name",
                      help="The node name of this pymq node. Every node in a pymq cluster must " +
                      "have a unique node name (default: morpheus)")
    parser.add_option("-g", "--profile", default=0,
                      action="store_const", const=1, dest="profile",
                      help="Profile the run using cProfile")
    parser.add_option("-d", "--datastore", default="MySQL",
                      action="store", dest="datastore", choices=["MySQL", "CachingMySQL"],
                      help="Use the specified file as the datastore module " +
                      "(options: MySQL, CachingMySQL) (default: MySQL)")
    parser.add_option("-s", "--connectionstring", default="root:@localhost",
                      action="store", dest="connectionstring",
                      help="The datastore connection string to use to initialize the datastore. " +
                      "The format of the connection string for the MySQL datastore is " +
                      "USERNAME:PASSWORD@HOSTNAME. The format is specific to the datastore " +
                      "that you are using (default: root:@localhost)")
    parser.add_option("-l", "--logger", default="stdout",
                      action="store", dest="logger", choices=["stdout", "none"],
                      help="Use the specified logger module (options: stdout, none) (default: stdout)")
    parser.add_option("-t", "--trace", default=0,
                      action="store_const", const=1, dest="trace",
                      help="Trace the execution of pymq, line by line (warning: this will result " +
                      "in a lot of lines being printed to the console)")
    parser.add_option("-i", "--inactive", default=0,
                      action="store_const", const=1, dest="inactive",
                      help="Run this pymq node in passive mode. This means that this node " +
                      "will not actively serve any requests till the master node instructs " +
                      "it to do so. If this option is specified, the -c (--cluster) option " +
                      "must also be specified")
    parser.add_option("-c", "--cluster", default="",
                      action="store", dest="cluster",
                      help="This specifies the location of the master node (default: <EMPTY>). " +
                      "Format: HOSTNAME:PORT. eg: localhost:9070. If left empty, this node will " +
                      "be started in stand-alone mode. " +
                      "This option MUST be specified along with the -i (--inactive) option")
    parser.add_option("-m", "--master", default=0,
                      action="store_const", const=1, dest="master",
                      help="Specifying this flag means that this node is going to be the pymq master " +
                      "node in the cluster")
    parser.add_option("-p", "--port", default="8070",
                      action="store", dest="port",
                      help="The port that this pymq node should listen on. This option should be specified " +
                      "for both normal as well as master nodes")
    (options, args) = parser.parse_args()
    # print options

    global DataStore, logger, master, cluster, inactive, port, name, cStr

    _tmp = __import__(options.datastore, globals=globals(), locals=locals())
    if not _tmp:
        print "Module %s was not found" % options.datastore
    DataStore = _tmp

    DataStore.setConnectionString(options.connectionstring)

    loggers = { "stdout": medusa_logger.file_logger(sys.stdout),
                "none": null_logger.null_logger() }
    if options.logger not in loggers.keys():
        print "The option '%s' is not valid as an option for a logger" % options.logger
    logger = loggers[options.logger]

    master   = options.master
    cluster  = options.cluster
    inactive = options.inactive
    port     = int(options.port)
    name     = options.name
    cStr     = options.connectionstring

    def pymq_print_trace(frame, event, arg):
        print "file: %s, line: %s, function: %s" % (frame.f_code.co_filename,
                                                    frame.f_lineno,
                                                    frame.f_code.co_name)
        return pymq_print_trace

    if (options.trace == 1):
        sys.settrace(pymq_print_trace)

    # sys.exit(1)
    sys.setcheckinterval(130)
    if options.profile == 1:
        import cProfile
        cProfile.run('profile_run()', 'pymq.cProfile', sort='time')
    else:
        # An interval of 130 gives the best performance on my system
        begin.run(port = port, logger = logger, DataStore = DataStore,
                  inactive = inactive, cluster = cluster, master = master,
                  name=name, connectionString=cStr)

if __name__ == "__main__":
    sys.exit(main(len(sys.argv), sys.argv))
